@echo off
setlocal enabledelayedexpansion

echo [INFO] Starting xhs-login-service...
echo [INFO] Using local JRE and pre-installed Playwright drivers.

rem Generate and display machine code
call :GetMachineCode machine_code_result hardware_info_result
echo =======================================================
echo Machine Code (SHA256):     !machine_code_result!
echo =======================================================
echo.

set "license_file=%USERPROFILE%\xhs_license_key.txt"
set "license_key="

if exist "!license_file!" (
    echo [INFO] Found existing license key file.
    
    call :ReadLicenseKey "!license_file!"

    if defined license_key (
        echo [INFO] Current license key: !license_key!
        echo.
        CHOICE /C YN /N /T 5 /D N /M "Do you want to modify the license key? (y/N): "
        if !errorlevel! equ 1 (
            set "modify_key=Y"
        ) else (
            set "modify_key=N"
        )
        echo.

        if /i "!modify_key!"=="y" (
            echo.
            set /p "new_license_key=Please enter new license key: "
            if "!new_license_key!"=="" (
                echo [ERROR] License key cannot be empty.
                pause
                exit /b 1
            )
            echo !new_license_key! > "!license_file!"
            set "license_key=!new_license_key!"
            echo [INFO] License key updated and saved.
        ) else (
            echo [INFO] Using existing license key.
        )
    ) else (
        echo [WARN] License key file is empty, please enter a new one.
        goto :input_new_key
    )
) else (
    echo [INFO] No existing license key found.
    :input_new_key
    set /p "license_key=Please enter your license key: "
    if "!license_key!"=="" (
        echo [ERROR] License key cannot be empty.
        pause
        exit /b 1
    )
    echo !license_key! > "!license_file!"
    echo [INFO] License key saved to: !license_file!
)

echo [INFO] License key provided: !license_key!
echo [INFO] Starting application with license validation...
".\jdk-17.0.15+6-jre\bin\java.exe" -Dfile.encoding=UTF-8 -DPLAYWRIGHT_BROWSERS_PATH=".\data\.ms-playwright" -Dplaywright.skip.browser.download=true -classpath ".\app;.\lib\*" com.xhs.XhsLoginServiceApplication --app.license-key="!license_key!"
pause
goto :eof

:ReadLicenseKey
setlocal enabledelayedexpansion
set "temp_license_key="
for /f "usebackq delims=" %%i in (%1) do (
    set "temp_license_key=%%i"
    goto :license_read_done
)
:license_read_done
endlocal & set "license_key=%temp_license_key%"
goto :eof

:GetMachineCode
setlocal enabledelayedexpansion

REM Section 1: Initialize variables
set "cpu_id="
set "board_serial="
set "disk_serial="
set "mac_address="
set "os_install_id="

REM Section 2: Get CPU Serial Number
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-WmiObject -Class Win32_Processor | Select-Object -First 1).ProcessorId } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "cpu_id=%%i" & goto cpu_done )
)
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-CimInstance -ClassName Win32_Processor | Select-Object -First 1).ProcessorId } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "cpu_id=%%i" & goto cpu_done )
)
:cpu_done
if not defined cpu_id ( set "cpu_id=FALLBACK_CPU_%USERNAME%" )

REM Section 3: Get Motherboard Serial Number
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { $board = (Get-WmiObject -Class Win32_BaseBoard | Select-Object -First 1).SerialNumber; if ($board -and $board -notmatch '^(ToBeFilledByO\.E\.M\.|NotAvailable|Default.*|^\\s*$)') { $board } else { '' } } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "board_serial=%%i" & goto board_done )
)
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { $board = (Get-CimInstance -ClassName Win32_BaseBoard | Select-Object -First 1).SerialNumber; if ($board -and $board -notmatch '^(ToBeFilledByO\.E\.M\.|NotAvailable|Default.*|^\\s*$)') { $board } else { '' } } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "board_serial=%%i" & goto board_done )
)
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-WmiObject -Class Win32_BaseBoard | Select-Object -First 1).Product } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "board_serial=%%i" & goto board_done )
)
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-CimInstance -ClassName Win32_BaseBoard | Select-Object -First 1).Product } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "board_serial=%%i" & goto board_done )
)
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-WmiObject -Class Win32_BaseBoard | Select-Object -First 1).Manufacturer } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "board_serial=%%i" & goto board_done )
)
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-WmiObject -Class Win32_ComputerSystem | Select-Object -First 1).Model } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "board_serial=%%i" & goto board_done )
)
:board_done
if not defined board_serial ( set "board_serial=FALLBACK_BOARD_%USERNAME%" )

REM Section 4: Get Hard Disk Serial Number
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-WmiObject -Class Win32_DiskDrive | Where-Object { $_.MediaType -like '*fixed*' } | Select-Object -First 1).SerialNumber } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "disk_serial=%%i" & goto disk_done )
)
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-CimInstance -ClassName Win32_DiskDrive | Where-Object { $_.MediaType -like '*fixed*' } | Select-Object -First 1).SerialNumber } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "disk_serial=%%i" & goto disk_done )
)
for /f "tokens=2" %%i in ('vol c: 2^>nul ^| findstr "Serial Number"') do (
    if "%%i" neq "" ( set "disk_serial=%%i" & goto disk_done )
)
:disk_done
if not defined disk_serial ( set "disk_serial=FALLBACK_DISK_%USERNAME%" )

REM Section 5: Get First Network MAC Address
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled -eq $true -and $_.MACAddress } | Select-Object -First 1).MACAddress } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "mac_address=%%i" & goto mac_done )
)
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled -eq $true -and $_.MACAddress } | Select-Object -First 1).MACAddress } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "mac_address=%%i" & goto mac_done )
)
for /f "tokens=1" %%i in ('getmac /fo table /nh 2^>nul ^| findstr /v "N/A" ^| findstr "-"') do (
    if "%%i" neq "" ( set "mac_address=%%i" & goto mac_done )
)
:mac_done
if not defined mac_address ( set "mac_address=FALLBACK_MAC_%USERNAME%" )

REM Section 6: Get OS Installation ID
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-WmiObject -Class Win32_OperatingSystem).InstallDate } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "os_install_id=%%i" & goto os_done )
)
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "try { (Get-CimInstance -ClassName Win32_OperatingSystem).InstallDate } catch { '' }" 2^>nul') do (
    if "%%i" neq "" ( set "os_install_id=%%i" & goto os_done )
)
for /f "tokens=3" %%i in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v InstallDate 2^>nul') do (
    if "%%i" neq "" ( set "os_install_id=%%i" & goto os_done )
)
:os_done
if not defined os_install_id ( set "os_install_id=FALLBACK_OS_%USERNAME%" )

REM Section 7: Combine Info and Generate SHA256 Hash
set "hardware_info=!cpu_id!-!board_serial!-!disk_serial!-!mac_address!-!os_install_id!"

REM First cleanup: remove obvious spaces and tabs
set "hardware_info=!hardware_info: =!"
set "hardware_info=!hardware_info:	=!"

REM Comprehensive cleanup using PowerShell: remove ALL whitespace characters
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "$input='!hardware_info!'; $cleaned=$input -replace '\\s+',''; $cleaned -replace '[\\r\\n\\t]',''; $cleaned"') do (
    set "hardware_info=%%i"
)

REM Final verification cleanup - remove any remaining spaces
set "hardware_info=!hardware_info: =!"

set "machine_code="

rem Use PowerShell to generate SHA256 hash
for /f "delims=" %%i in ('powershell -ExecutionPolicy Bypass -Command "$hashInput = '!hardware_info!'; $bytes = [System.Text.Encoding]::UTF8.GetBytes($hashInput); $hash = [System.Security.Cryptography.SHA256]::Create().ComputeHash($bytes); ($hash | ForEach-Object { $_.ToString('x2') }) -join ''"') do (
    if "%%i" neq "" ( set "machine_code=%%i" )
)

rem If PowerShell fails, use the raw hardware info string directly for a stable code
if not defined machine_code (
    set "machine_code=!hardware_info!"
)

rem Section 8: Return both the SHA256 hash and the hardware info
endlocal & set "%1=%machine_code%" & set "%2=%hardware_info%"
goto :eof
